package org.demo.warehouse.controller;


import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.demo.warehouse.common.exception.BusinessException;
import org.demo.warehouse.common.pojo.Goods;
import org.demo.warehouse.common.pojo.Record;
import org.demo.warehouse.common.pojo.User;
import org.demo.warehouse.common.utils.PageParam;
import org.demo.warehouse.common.utils.R;
import org.demo.warehouse.service.IGoodsService;
import org.demo.warehouse.service.IRecordService;
import org.demo.warehouse.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Random;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author zgc
 * @since 2021-12-16
 */
@Slf4j
@RestController
@RequestMapping("/record")
public class RecordController extends AbstractController<Record> {
    @Autowired
    private IRecordService recordService;
    @Autowired
    private IGoodsService goodsService;
    @Autowired
    private IUserService userService;

    @GetMapping("/page")
    @Override
    public R page(PageParam param) {
        return R.ok(recordService.pageVo(new Page<>(param.getPage(), param.getLimit()), param.getWrapper()));
    }

    @Override
    protected void handleBeanBeforeSave(Record record) {
        if (!updateGoodsAmount(record, false)) {
            throw new BusinessException("操作失败，商品库存不足");
        }
    }

    @Override
    protected void handleBeanBeforeDelete(Long id) {
        Record record = recordService.getById(id);
        if (!updateGoodsAmount(record, true)) {
            throw new BusinessException("操作失败，商品库存不足");
        }
    }

    @GetMapping("/statistic/{type}")
    public R statistic(@PathVariable Integer type) {
        return R.ok(recordService.getStatistic(type));
    }

    @GetMapping("/generator/{size}")
    public R generatorRecord(@PathVariable Long size) {
        List<Goods> goods = goodsService.list();
        Map<Long, List<User>> users = userService.list().stream().collect(Collectors.groupingBy(User::getRoleId, Collectors.toList()));
        Random random = new Random();
        Stream.generate(() -> random.nextInt(2) + 1).parallel().limit(size).map(type -> {
            Goods selectedGoods = goods.get(random.nextInt(goods.size()));
            List<User> selectedUsers = users.get(Long.valueOf(type));
            User selectedUser = selectedUsers.get(random.nextInt(selectedUsers.size()));
            int amount = random.nextInt(100) + 1;
            LocalDateTime createTime = LocalDateTime.now().plusDays(-random.nextInt(7));
            Record record = new Record();
            record.setType(type)
                    .setGoodsId(selectedGoods.getId())
                    .setUserId(selectedUser.getId())
                    .setSum(amount)
                    .setCreateTime(createTime);
            return updateGoodsAmount(record, false) ? record : null;
        }).filter(Objects::nonNull).collect(Collectors.collectingAndThen(Collectors.toList(), recordService::saveBatch));
        return R.ok();
    }

    /**
     * 更新商品库存
     *
     * @param record
     * @param rollback
     * @return
     */
    private synchronized boolean updateGoodsAmount(Record record, boolean rollback) {
        Long goodsId = record.getGoodsId();
        Goods goods = goodsService.getById(goodsId);
        int num = Record.RECORD_TYPE_IN.equals(record.getType()) ? record.getSum() :
                -record.getSum();
        if (rollback) {
            num = -num;
        }
        int amount = goods.getAmount() - num;
        if (amount < 0) {
            log.warn(goods.getName() + "库存不足，已撤回出入库操作！");
            return false;
        }
        goods.setAmount(amount);
        return goodsService.saveOrUpdate(goods);
    }
}

